package asm;

import org.objectweb.asm.*;
import org.objectweb.asm.commons.AdviceAdapter;

import static org.objectweb.asm.Opcodes.ASM7;

public class G_adviceMethod {
    public void adviceMethodByCoreAPI() throws Exception {
        ClassReader cr = Tool.getClassReader();
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
        ClassVisitor cv = new ClassVisitor(ASM7, cw) {


            @Override
            public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
                MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);

                if (!"test01".equals(name)) {
                    return mv;
                }
                // 修改test01 进入方法
                return new AdviceAdapter(ASM7, mv, access, name, descriptor) {
                    @Override
                    protected void onMethodEnter() {
                        super.onMethodEnter();
                        mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
                        mv.visitLdcInsn("enter method");
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);

                    }

                    // 退出方法
                    @Override
                    protected void onMethodExit(int opcode) {
                        super.onMethodExit(opcode);
                        mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
                        // 异常
                        if (opcode == Opcodes.ATHROW) {
                            mv.visitLdcInsn("out method -- exception");
                        } else {
                            mv.visitLdcInsn("out method -- normal ");
                        }

                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
                    }
                };
            }

        };
        //cr.accept(cv,ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG);
        cr.accept(cv, 0);
        byte[] bytesModifield = cw.toByteArray();

        Tool.save(this.getClass(), Application.class, bytesModifield);

    }



    public static void main(String[] args) throws Exception {
        G_adviceMethod advice = new G_adviceMethod();
        // 修改方法
        advice.adviceMethodByCoreAPI();
        // 调用类
        new Application().test01();
    }
}
